import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:barcode_scan2/platform_wrapper.dart';
import 'package:book_app/feature/devices/extra.dart';
import 'package:book_app/feature/devices/search_device.dart';
import 'package:book_app/feature/devices/view/connected_device_tile.dart';
import 'package:book_app/feature/devices/view/scan_camera_view.dart';
import 'package:book_app/feature/devices/view/scan_result_tile.dart';
import 'package:book_app/feature/devices/view/snackbar.dart';
import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:hex/hex.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';

import 'device_screen.dart';
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:book_app/feature/devices/utilshelp.dart';

class ScanScreen extends StatefulWidget {
  const ScanScreen({Key? key}) : super(key: key);

  @override
  State<ScanScreen> createState() => _ScanScreenState();
}

class _ScanScreenState extends State<ScanScreen> {
  List<BluetoothDevice> _connectedDevices = [];
  List<ScanResult> _scanResults = [];
  List<String> _remoteIds = [];
  bool _isScanning = false;
  late StreamSubscription<List<ScanResult>> _scanResultsSubscription;
  late StreamSubscription<bool> _isScanningSubscription;

  BluetoothDevice? device;
  BluetoothCharacteristic? writeCharacteristic;

  List<BluetoothService> _services = [];
  List<String> remotesId = [];

  late StreamSubscription<List<int>> _lastValueSubscription; //字节流

  List<int> _value = [];

  final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
  Barcode? result;
  QRViewController? controller;

  @override
  void initState() {
    super.initState();

    ///连接设备的监听
    FlutterBluePlus.systemDevices.then((devices) {
      _connectedDevices = devices;
      setState(() {});
    });

    ///扫描设备
    _scanResultsSubscription = FlutterBluePlus.scanResults.listen((results) {
      ///iOS 扫描
      for (ScanResult result in results) {
        if (result.advertisementData.manufacturerData != null) {
          if (result.advertisementData.manufacturerData.keys.contains(1827) ||
              result.advertisementData.manufacturerData.keys.contains(1828)) {
            result.advertisementData.manufacturerData.forEach((key, value) {
              if (value != null && value.length > 13) {
                int dpid = value![8] * 0x1000000 +
                    value![9] * 0x10000 +
                    value![10] * 0x100 +
                    value![11];
                int flag = value[13]; //0x00未添加 0x01成功添加过 0x02上一次添加失败
                if (flag == 0) {
                  if (dpid >= 1) {
                    String remoteID = "";
                    if(Platform.isAndroid){
                      remoteID = result.device.remoteId.str;
                    }else{
                      remoteID = result.device.remoteId.str;
                    }
                    print("唯一标识${remoteID}${_remoteIds}");
                    if (!_remoteIds.contains(remoteID)) {
                      _remoteIds.add(remoteID);
                      _scanResults.add(result);
                    }
                  }
                }
              }
            });
          }
        }
        if (result.advertisementData.serviceData != null) {
          if (result.advertisementData.serviceData.keys
                  .contains(Guid("1827")) ||
              result.advertisementData.serviceData.keys
                  .contains(Guid("1828"))) {
            result.advertisementData.serviceData.forEach((key, value) {
              if (value != null && value.length >= 12) {
                int dpid = value![8] * 0x1000000 +
                    value![9] * 0x10000 +
                    value![10] * 0x100 +
                    value![11];
                int flag = value[13]; //0x00未添加 0x01成功添加过 0x02上一次添加失败
                if (0 == 0) {
                  if (dpid >= 1) {
                    if (!_scanResults .contains(result)) {
                      _scanResults.add(result);
                    }
                  }
                  print(
                      "获取到设备的类型:${result.advertisementData.serviceData} ${dpid} Mac地址${result.device.remoteId}");
                }
              }
            });
          }
        }
      }
      setState(() {});
    });

    _isScanningSubscription = FlutterBluePlus.isScanning.listen((state) {
      _isScanning = state;
      setState(() {});
    });
  }

  @override
  void dispose() {
    _scanResultsSubscription.cancel();
    _isScanningSubscription.cancel();

    super.dispose();
  }

  Future onScanPressed() async {
    try {
      // android is slow when asking for all advertisments,
      // so instead we only ask for 1/8 of them
      int divisor = Platform.isAndroid ? 8 : 1; //判断是否是安卓
      //蓝牙开始搜索设备
      _scanResults.clear(); //先晴空旧数据

      await FlutterBluePlus.startScan(
          timeout: const Duration(seconds: 15),
          continuousUpdates: true,
          continuousDivisor: divisor);
    } catch (e) {
      Snackbar.show(ABC.b, prettyException("Start Scan Error:", e),
          success: false);
    }
    setState(() {}); // force refresh of systemDevices
  }

  Future onStopPressed() async {
    try {
      //停止扫描
      FlutterBluePlus.stopScan();
    } catch (e) {
      Snackbar.show(ABC.b, prettyException("Stop Scan Error:", e),
          success: false);
    }
  }

  void onConnectPressed(BluetoothDevice device, BuildContext context) {
    _showMyDialog(device, context);
    // device.connectAndUpdateStream().catchError((e) {
    //   Snackbar.show(ABC.c, prettyException("Connect Error:", e),
    //       success: false);
    // });
    // MaterialPageRoute route = MaterialPageRoute(
    //     builder: (context) => DeviceScreen(device: device),
    //     settings: RouteSettings(name: '/DeviceScreen'));
    // Navigator.of(context).push(route);
  }

  Future onRefresh() {
    if (_isScanning == false) {
      FlutterBluePlus.startScan(timeout: const Duration(seconds: 15));
    }
    setState(() {});
    return Future.delayed(Duration(milliseconds: 500));
  }

  Widget buildScanButton(BuildContext context) {
    if (FlutterBluePlus.isScanningNow) {
      return FloatingActionButton(
        child: const Icon(Icons.stop),
        onPressed: onStopPressed,
        backgroundColor: Colors.red,
      );
    } else {
      return FloatingActionButton(
          child: const Text("SCAN"), onPressed: onScanPressed);
    }
  }

  List<Widget> _buildConnectedDeviceTiles(BuildContext context) {
    return _connectedDevices
        .map(
          (d) => ConnectedDeviceTile(
            device: d,
            onOpen: () => Navigator.of(context).push(
              MaterialPageRoute(
                builder: (context) => DeviceScreen(device: d),
                settings: RouteSettings(name: '/DeviceScreen'),
              ),
            ),
            onConnect: () => onConnectPressed(d, context),
          ),
        )
        .toList();
  }

  List<Widget> _buildScanResultTiles(BuildContext context) {
    return _scanResults
        .map(
          (r) => ScanResultTile(
            result: r,
            onTap: () => onConnectPressed(r.device, context),
          ),
        )
        .toList();
  }

  @override
  Widget build(BuildContext context) {
    return ScaffoldMessenger(
      key: Snackbar.snackBarKeyB,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Find Devices'),
          actions: [buildScan()],
        ),
        body: RefreshIndicator(
          onRefresh: onRefresh,
          child: ListView(
            children: <Widget>[
              ..._buildConnectedDeviceTiles(context),
              ..._buildScanResultTiles(context),
            ],
          ),
        ),
        floatingActionButton: buildScanButton(context),
      ),
    );
  }

  //弹窗提示
  _showMyDialog(BluetoothDevice selectDevice, BuildContext context) async {
    onStopPressed();
    device = selectDevice;
    final result = await showModalActionSheet<String>(
      context: context,
      style: AdaptiveStyle.iOS,
      cancelLabel: "取消",
      actions: [
        const SheetAction(
          label: '识别设备',
          key: 'identify',
        ),
        const SheetAction(
          label: '取消识别设备',
          key: 'cancelIdentify',
        ),
        const SheetAction(
          label: '添加设备',
          key: 'addDevice',
          isDestructiveAction: true,
        ),
        const SheetAction(
          label: '断开连接',
          key: 'disConnected',
          isDestructiveAction: true,
        ),
        const SheetAction(
          label: '配置密码',
          key: 'wifi',
          isDestructiveAction: true,
        ),
      ],
    );
    if (result == "disConnected") {
      print("点击断开连接");
      onCancelPressed();
    } else if (result == "identify") {
      print("点击了识别设备");
      device = selectDevice;
      selectDevice.connectionState
          .listen((BluetoothConnectionState state) async {
        print("蓝牙连接状态监听");
        if (state == BluetoothConnectionState.disconnected) {
          print("蓝牙断开断开");
          // 1. typically, start a periodic timer that tries to
          //    reconnect, or just call connect() again right now
          // 2. you must always re-discover services after disconnection!
          // print("${device.disconnectReasonCode} ${device.disconnectReasonDescription}");
        } else if (state == BluetoothConnectionState.connected) {
          print("蓝牙连接成功");
          if (Platform.isAndroid) {
            int mtu = await selectDevice.requestMtu(77);//设置最大MTU
            print("请求Mtu${mtu}");
          }
          _onDiscoverServicesPressed();
        }
      });
      selectDevice.connectAndUpdateStream().catchError((e) {

      });
    } else if (result == "cancelIdentify") {
      print("点击了取消识别设备");
      cancelIdentifyToCharacteristic();
    } else if (result == "wifi") {
      print("配置Wi-Fi");
      _showWifiPwdUI(context);
    } else {
      print("点击了添加设备");
      // listen for disconnection
    }
  }

  ///发现服务
  _onDiscoverServicesPressed() async {
    if (device != null) {
      try {
        _services = (await device?.discoverServices(timeout: 20))!;
        Snackbar.show(ABC.c, "Discover Services: Success", success: true);
        Guid customOtaServiceUUID =
            Guid("3ff40001-0e4f-4f99-91e9-2b0a87a580c4");
        Guid customCharacteristicNotifyUUID =
            Guid("3ff40002-0e4f-4f99-91e9-2b0a87a580c4");
        Guid customCharacteristicWriteUUID =
            Guid("3ff40003-0e4f-4f99-91e9-2b0a87a580c4");
        Guid kSILOtaServiceUUID = Guid("1D14D6EE-FD63-4FA1-BFA4-8F47B42119F0");
        Guid kSILOtaCharacteristicOTADataAttributeUUID =
            Guid("984227F3-34FC-4045-A5D0-2C581F81A153");
        Guid kSILOtaCharacteristicOTAControlAttributeUUID =
            Guid("F7BF3564-FB6D-4E53-88A4-5E37E0326063");
        for (var element in _services) {
          // BluetoothService
          String serviceUuidString = element.serviceUuid.toString();
          if (serviceUuidString == customOtaServiceUUID.toString() ||
              serviceUuidString == customCharacteristicNotifyUUID.toString() ||
              serviceUuidString == customCharacteristicWriteUUID.toString()) {
            bool findService = false;
            for (BluetoothCharacteristic characteristic
                in element.characteristics) {
              String characteristicUuidString =
                  characteristic.characteristicUuid.toString();
              if (characteristicUuidString ==
                  customCharacteristicWriteUUID.toString()) {
                if (characteristic.properties.write) {
                  print("发现的描述${characteristic.toString()}");
                  findService = true;
                  writeCharacteristic = characteristic; //
                  //可以写入的描述
                  writeDataToCharacteristic(characteristic);
                  break;
                } else {
                  print("未读取到写入的描述}");
                }
              }
            }
            if (!findService) {
              //没有发现服务
              onCancelPressed();
            }
          }
        }
      } catch (e) {
        Snackbar.show(ABC.c, prettyException("Discover Services Error:", e),
            success: false);
      }
    }
  }

  ///写数据
  writeDataToCharacteristic(BluetoothCharacteristic characteristic) {
    //原始数据
    int flag = 0x08;
    Uint8List originalData =
        Uint8List.fromList([0x01, 0x41, 0x40, 0x01, 0x3C]); //识别设备发送60秒
    Uint8List keyHex = Uint8List.fromList([
      0x61,
      0x3e,
      0x29,
      0xbc,
      0xda,
      0x52,
      0x58,
      0x45,
      0x1e,
      0xbb,
      0x1c,
      0x62,
      0xe2,
      0xa5,
      0xf6,
      0xcb
    ]);
    Uint8List ivHex = Uint8List.fromList([
      0xd7,
      0xe3,
      0x85,
      0xa5,
      0xed,
      0x77,
      0xa2,
      0x6f,
      0x7f,
      0x0d,
      0xd5,
      0xd7,
      0x5a,
      0x70,
      0x3b,
      0x47
    ]);
    //AES加密数据
    Uint8List encryptData =
        UtilsHelp.processingDataPack(originalData, keyHex, ivHex, 0xCA, flag);
    onWritePressed(characteristic, encryptData);
  }

  cancelIdentifyToCharacteristic() {
    //原始数据
    if (writeCharacteristic != null) {
      int flag = 0x08;
      Uint8List originalData =
          Uint8List.fromList([0x01, 0x41, 0x40, 0x01, 0x00]); //取消识别设备发送0秒
      Uint8List keyHex = Uint8List.fromList([
        0x61,
        0x3e,
        0x29,
        0xbc,
        0xda,
        0x52,
        0x58,
        0x45,
        0x1e,
        0xbb,
        0x1c,
        0x62,
        0xe2,
        0xa5,
        0xf6,
        0xcb
      ]);
      Uint8List ivHex = Uint8List.fromList([
        0xd7,
        0xe3,
        0x85,
        0xa5,
        0xed,
        0x77,
        0xa2,
        0x6f,
        0x7f,
        0x0d,
        0xd5,
        0xd7,
        0x5a,
        0x70,
        0x3b,
        0x47
      ]);
      //AES加密数据
      Uint8List encryptData =
          UtilsHelp.processingDataPack(originalData, keyHex, ivHex, 0xCA, flag);
      onWritePressed(writeCharacteristic!, encryptData);
    }
  }

  ///写入蓝牙数据
  Future onWritePressed(
      BluetoothCharacteristic characteristic, Uint8List encryptData) async {
    try {
      await characteristic.write(encryptData,
          withoutResponse: false, allowLongWrite: true, timeout: 15);
      print("Write: Success写入加密的数据${HEX.encode(encryptData)}");
      if (characteristic.properties.read) {
        await characteristic.read();
      }
    } catch (e) {
      print("写入加密的数据${e.toString()}");
    }

    _lastValueSubscription = characteristic.lastValueStream.listen((value) {
      _value = value;
      decryptValue(value);
    });
  }

  Future onSubscribePressed() async {
    try {
      String op = writeCharacteristic?.isNotifying == false
          ? "Subscribe"
          : "Unubscribe";
      await writeCharacteristic
          ?.setNotifyValue(writeCharacteristic?.isNotifying == false);
      Snackbar.show(ABC.c, "$op : Success", success: true);
      if (writeCharacteristic!.properties.read) {
        await writeCharacteristic?.read();
      }
      setState(() {});
    } catch (e) {
      Snackbar.show(ABC.c, prettyException("Subscribe Error:", e),
          success: false);
    }
  }

  ///断开连接
  Future onCancelPressed() async {
    if (device != null) {
      try {
        await device?.disconnectAndUpdateStream(queue: false);
        Snackbar.show(ABC.c, "Cancel: Success", success: true);
      } catch (e) {
        Snackbar.show(ABC.c, prettyException("Cancel Error:", e),
            success: false);
      }
    }
  }

  _showWifiPwdUI(BuildContext context) async {
    final text = await showTextInputDialog(
      context: context,
      style: AdaptiveStyle.iOS,
      textFields: const [
        DialogTextField(
          hintText: 'Email',
          initialText: 'AcTEC',
        ),
        DialogTextField(
          hintText: 'Password',
          obscureText: true,
        ),
      ],
      title: 'Hello',
      message: 'This is a message',
    );
    String? ssid = text?.first;
    String? pwd = text?.last;
    if (ssid != null && ssid!.isEmpty) {
      EasyLoading.showToast("请输入Wi-Fi名称");
      return;
    }
    if (pwd != null && pwd!.isEmpty) {
      EasyLoading.showToast("请输入Wi-Fi密码");
      return;
    }
    setWifiPwd(ssid, pwd);
  }

  ///设置Wi-Fi
  setWifiPwd(String? ssid, String? pwd) {
    //设置Wi-Fi密码

    if (writeCharacteristic != null) {
      int flag = 0x08;
      List<int> headList = [0x01, 0x51, 0x40];
      List<int> ssidList = utf8.encode(ssid!);
      List<int> pwdList = utf8.encode(pwd!);

      List<int> originalData = [];
      originalData.addAll([ssidList.length & 0xff]);
      originalData.addAll(ssidList);
      originalData.addAll([pwdList.length & 0xff]);
      originalData.addAll(pwdList);
      originalData.addAll([0x00, 0x3C]);

      List<int> totalData = [];
      totalData.addAll(headList);
      totalData.addAll([originalData.length]);
      totalData.addAll(originalData);

      print("写入原始串的数据${HEX.encode(totalData)}");

      Uint8List keyHex = Uint8List.fromList([
        0x61,
        0x3e,
        0x29,
        0xbc,
        0xda,
        0x52,
        0x58,
        0x45,
        0x1e,
        0xbb,
        0x1c,
        0x62,
        0xe2,
        0xa5,
        0xf6,
        0xcb
      ]);
      Uint8List ivHex = Uint8List.fromList([
        0xd7,
        0xe3,
        0x85,
        0xa5,
        0xed,
        0x77,
        0xa2,
        0x6f,
        0x7f,
        0x0d,
        0xd5,
        0xd7,
        0x5a,
        0x70,
        0x3b,
        0x47
      ]);
      //AES加密数据
      Uint8List encryptData = UtilsHelp.processingDataPack(
          Uint8List.fromList(totalData), keyHex, ivHex, 0xC9, flag);
      print("写入加密串的数据${HEX.encode(encryptData)}");
      onWritePressed(writeCharacteristic!, encryptData);
    }
  }

  ///解密
  decryptValue(List<int> value) {
    if (value.length > 5) {
      Uint8List originalList = Uint8List.fromList(value.sublist(5));
      Uint8List keyHex = Uint8List.fromList([
        0x61,
        0x3e,
        0x29,
        0xbc,
        0xda,
        0x52,
        0x58,
        0x45,
        0x1e,
        0xbb,
        0x1c,
        0x62,
        0xe2,
        0xa5,
        0xf6,
        0xcb
      ]);
      Uint8List ivHex = Uint8List.fromList([
        0xd7,
        0xe3,
        0x85,
        0xa5,
        0xed,
        0x77,
        0xa2,
        0x6f,
        0x7f,
        0x0d,
        0xd5,
        0xd7,
        0x5a,
        0x70,
        0x3b,
        0x47
      ]);
      Uint8List decryptList =
          UtilsHelp.AES128DecryptWithKey(originalList, keyHex, ivHex);
      print("收到蓝牙的解密数据${HEX.encode(decryptList)}");
    }
  }

  Widget buildScan() {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 12),
      child: ElevatedButton(
        style: ElevatedButton.styleFrom(
          foregroundColor: Colors.white,
          backgroundColor: Colors.grey.shade700,
        ),
        onPressed: scanNode,
        child: const Text('扫一扫'),
      ),
    );
  }

  scanNode() async {
    // Navigator.of(context).push(MaterialPageRoute(
    //   builder: (context) => const QRViewExample(),
    // ));
    Navigator.of(context).push(MaterialPageRoute(
      builder: (context) => const ChargingStationSelector(),
    ));
  }
}
